home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / dbwrend / source / int.c < prev    next >
Text File  |  1989-04-16  |  9KB  |  276 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1987, David B. Wecker                 *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * This file is part of DBW_Render                                      *
  7.  *                                                                      *
  8.  * DBW_Render is distributed in the hope that it will be useful, but    *
  9.  * WITHOUT ANY WARRANTY. No author or distributor accepts               *
  10.  * responsibility to anyone for the consequences of using it or for     *
  11.  * whether it serves any particular purpose or works at all, unless     *
  12.  * he says so in writing. Refer to the DBW_Render General Public        *
  13.  * License for full details.                                            *
  14.  *                                                                      *
  15.  * Everyone is granted permission to copy, modify and redistribute      *
  16.  * DBW_Render, but only under the conditions described in the           *
  17.  * DBW_Render General Public License. A copy of this license is         *
  18.  * supposed to have been given to you along with DBW_Render so you      *
  19.  * can know your rights and responsibilities. It should be in a file    *
  20.  * named COPYING. Among other things, the copyright notice and this     *
  21.  * notice must be preserved on all copies.                              *
  22.  ************************************************************************
  23.  *                                                                      *
  24.  * Authors:                                                             *
  25.  *      DBW - David B. Wecker                                           *
  26.  *                                                                      *
  27.  * Versions:                                                            *
  28.  *      V1.0 870125 DBW - First released version                        *
  29.  *                                                                      *
  30.  ************************************************************************/
  31.  
  32. /* INT.C - calculations for ray intersections with primitives */
  33.  
  34. #define MODULE_INTER
  35. #include "ray.h"
  36.  
  37. node *get_next_intersection(which,best_p,best_t)
  38. int         which;
  39. vector      best_p;
  40. float       *best_t;
  41. {
  42.      /* This routine returns the pertinent data for the i'th intersection */
  43.  
  44.      if (which >= g_objcounter)
  45.           return NULL;  /* No more intersections */
  46.      else
  47.      {
  48.           *best_t   = g_distances[which];
  49.           veccopy(g_points[which],best_p);
  50.           return g_objpairs[which];
  51.      }
  52. }
  53.  
  54.  
  55. void add_intersection(np,p,t,attenuating)
  56. node        *np;
  57. vector      p;
  58. float       t;
  59. int         attenuating;
  60. {
  61.      int add;
  62.  
  63. /* 
  64.  *   This routine adds the passed intersection information to the global list
  65.  *   of intersections.  As a performance optimization,if we know that all
  66.  *   objects are opaque,then rather than accumulating the entire list and
  67.  *   sorting it later,we merely keep track of the closest intersection.
  68.  */
  69.      add = FALSE;
  70.  
  71.      if ( allopaque    == 0 ||  /* Some transparency, all everything */
  72.           g_objcounter == 0 ||  /* First opaque intersection         */
  73.           t < g_distances[0])
  74.      {
  75.           add = TRUE;  /* Nearer opaque intersection */
  76.      }
  77.      
  78.      if ( attenuating &&
  79.          np->attr.tra[0] >= .99 &&
  80.          np->attr.tra[1] >= .99 &&
  81.          np->attr.tra[2] >= .99)
  82.      {
  83.                add = FALSE;  /* ignore invisible objects when doing shadows */
  84.      }
  85.  
  86.      if (add) 
  87.      {
  88.           g_distances[g_objcounter] = t;
  89.           veccopy(p,g_points[g_objcounter]);
  90.           g_objpairs[g_objcounter] = np;
  91.           if (g_objcounter < MAXOBJ)
  92.                g_objcounter++;
  93.      }
  94. }
  95.  
  96. void calc_intersections(np,eye,d,attenuating)
  97. node      *np;           /* current node                     */
  98. vector    d;             /* direction vector for current ray */
  99. vector    eye;           /* current ray origin (eye point)   */
  100. int       attenuating;   /* attenuation factor for each hit  */
  101. {
  102.  
  103. /* 
  104.  *   This routine calculates the intersection of a ray with a given object.
  105.  *   If an intersection is found,the appropriate parameters are added to a
  106.  *   global list.  This routine is recursive,to handle nested extents. 
  107.  */
  108.  
  109.      vector      p;
  110.      float       t;
  111.      int         hit;
  112.      long        curs;
  113.  
  114.      /* keep track of maximum stack extent */
  115.      curs = curstack();
  116.      if (curs < stackbot)
  117.           stackbot = curs;
  118.  
  119.      while (np) 
  120.      {
  121.           hit = FALSE;
  122.           switch (np->kind) 
  123.           {
  124.           case EXTENT :
  125.                if (hitsphere(eptr(np)->center,eptr(np)->radius,eye,d,p,&t))
  126.                     calc_intersections(eptr(np)->sub,eye,d,attenuating);
  127.                break;
  128.  
  129.           case SPHERE :
  130.                hit = hitsphere(sptr(np)->center,sptr(np)->radius,eye,d,p,&t);
  131.                break;
  132.  
  133.           case TRIANGLE :
  134.                hit = hittriangle(np,eye,d,p,&t);
  135.                break;
  136.  
  137.           case QUAD :
  138.                hit = hitquad(np,eye,d,p,&t);
  139.                break;
  140.  
  141.           case RING :
  142.                hit = hitring(np,eye,d,p,&t);
  143.                break;
  144.  
  145.           case CYLINDER :
  146.                hit = hitcylinder(np,eye,d,p,&t);
  147.                break;
  148.  
  149.           default :
  150.                hit = FALSE;
  151.                break;
  152.           }
  153.  
  154.           if (hit)
  155.                add_intersection(np,p,t,attenuating);  /* Add to global list */
  156.  
  157.           np = np->next;  /* On to the next object */
  158.      }
  159. }
  160.  
  161. void all_intersects(eye,d,attenuating)
  162. vector  d;
  163. vector  eye;
  164. int     attenuating;
  165. {
  166.  
  167. /* 
  168.  *   This routine computes all of the ray-object intersections that occur for
  169.  *   the specified ray.  The intersections are stored in global arrays, sorted
  170.  *   closest intersection to furthest. 
  171.  */
  172.  
  173.      g_objcounter = 0;  /* Clear the intersection list */
  174.  
  175.      calc_intersections(root,eye,d,attenuating);  /* Find them & add to list */
  176.  
  177.      if (g_objcounter > 1)
  178.           shell(g_distances,g_points,g_objpairs,g_objcounter);  /* Sort them */
  179.  
  180.      /* Keep statistics (and decide when to GIVE UP!!) */
  181.      if (++curr_runs >= max_runs)
  182.           longjmp(env,-1);
  183.  
  184.      if (g_objcounter > max_intersects)
  185.           max_intersects = g_objcounter;
  186. }
  187.  
  188. int bouncelighting(pseudointensity,pseudolitdir,bouncenp,lit)
  189. vector  pseudointensity,
  190.   pseudolitdir;
  191. node    *bouncenp;
  192. int     lit;
  193. {
  194.      vector n,bouncepoint,lightdir;
  195.  
  196.      if (bouncenp->kind == SPHERE || bouncenp->attr.ref == 0.0)
  197.           return FALSE;  /* No pseudo light source from here */
  198.      else
  199.      { 
  200.           switch (bouncenp->kind) 
  201.           {
  202.           case TRIANGLE :
  203.                veccopy(tptr(bouncenp)->position,bouncepoint);
  204.                break;
  205.           case QUAD     :
  206.                veccopy(qptr(bouncenp)->position,bouncepoint);
  207.                break;
  208.           case RING     :
  209.                veccopy(rptr(bouncenp)->position,bouncepoint);
  210.                break;
  211.           }
  212.           findnormal(bouncenp,bouncepoint,n);
  213.           veccopy(light[lit].direction,lightdir);  /* Assume directional light */
  214.           if (light[lit].kind != 0) 
  215.           { /* Point source */
  216.                DIRECTION(bouncepoint,lightdir,lightdir);
  217.           }
  218.  
  219.           vecscale(2.0 * DOT(lightdir,n),n,pseudolitdir);
  220.           vecsub(lightdir,pseudolitdir,pseudolitdir);
  221.           vecscale(bouncenp->attr.ref,light[lit].intensity,pseudointensity);
  222.           return TRUE;
  223.      }
  224. }
  225.  
  226. void blendcolor(original,target,scale,result)
  227. vector original;
  228. vector target;
  229. vector result;
  230. float  scale;
  231. {
  232.      vector path;
  233.  
  234.      if (scale < 0.0)
  235.           scale = 0.0;  /* clip off excessive blending */
  236.      if (scale > 1.0)
  237.           scale = 1.0;
  238.      vecsub(target,original,path);
  239.      vecscale(scale,path,path);
  240.      vecsum(original,path,result);
  241. }
  242.  
  243. void getatten(atten,p,d,lit,pointdist)
  244. vector atten;
  245. vector p;
  246. vector d;
  247. int    lit;
  248. float  pointdist;
  249. {
  250.      vector  best_p;
  251.      float   best_t;
  252.      int     hitnext;
  253.  
  254. #ifdef MCH_AMIGA
  255.      node    *occlude = 1L;
  256. #else
  257.      node    *occlude = (node *)1L;
  258. #endif
  259.  
  260.      atten[0] = 1.0;  /* assume no attenuation */
  261.      atten[1] = 1.0;
  262.      atten[2] = 1.0;
  263.      hitnext = 0;
  264.      all_intersects(p,d,1);  /* Compute all intersections */
  265.  
  266.      while (occlude && (atten[0] > 0.01 || atten[1] > 0.01 || atten[2] > 0.01))
  267.           if (occlude = get_next_intersection(hitnext,best_p,&best_t)) 
  268.           {
  269.                if (light[lit].kind == 0 || best_t <= pointdist) 
  270.                {
  271.                     vecmul(atten,occlude->attr.tra,atten);
  272.                }
  273.                hitnext++;
  274.           }
  275. }
  276.